package org.easy.eao.spring;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.easy.eao.Action;
import org.easy.eao.ActionBuilder;
import org.easy.eao.exception.CannotBuildActionException;
import org.easy.eao.utils.ActionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

/**
 * 存取动作创建者 for Spring
 * 
 * @author Frank
 */
public class SpringActionBuilder implements ActionBuilder, BeanFactoryAware {

	/** 日志对象 */
	static final Logger logger = LoggerFactory.getLogger(SpringEaoFactory.class);

	private ConfigurableListableBeanFactory beanFactory;

	@Override
	public List<Action<?>> buildActions(Class<?> clz, Method method, Set<Class<Action<?>>> actions) {
		List<Action<?>> instances = new ArrayList<Action<?>>();
		try {
			Map<Class<? extends Annotation>, Class<Action<?>>> actionMap = ActionUtils.toMap(actions);
			
			for (Annotation a : method.getAnnotations()) {
				Class<? extends Annotation> aClz = a.annotationType();
				if (!actionMap.containsKey(aClz))
					continue;
				Class<Action<?>> actionClz = actionMap.get(aClz);
				instances.add(initializeAction(actionClz, a, method, clz));
			}
		} catch (Exception e) {
			String message = "无法创建存取动作(Action)[class:" + clz.toString() + " method:" + method.toString() + " actions:"
					+ actions.toString() + "]";
			logger.error(message, e);
			throw new CannotBuildActionException(message, e);
		}
		return instances;
	}
	
	/**
	 * 初始化 Action 实例
	 * @param action Action's Class
	 * @param anno 当前方法上的注释实例
	 * @param method 当前方法
	 * @param clz 当前方法所在的 EAO Class
	 * @return
	 */
	private Action<?> initializeAction(Class<Action<?>> action, Annotation anno, Method method,
			Class<?> clz) {
		Action<? extends Annotation> result = null;
		try {
			result = (Action<?>) beanFactory.createBean(action);
			result.initialize(anno, method, clz);
		} catch (Exception e) {
			System.out.println(e);
			// 由于之前实例化过，所以这里的异常是不会出现的
		}
		return result;
	}

	// BeanFactoryAware's Method
	
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
	}

}
